var nodetext;
var nodekey;

var nodeattrlist = [];

function init() {
	var $ = go.GraphObject.make; // for conciseness in defining templates

	myDiagram = $(go.Diagram, "myDiagramDiv", // must name or refer to the div
	{
		initialContentAlignment : go.Spot.Center,
		allowDrop : true, // must be true to accept drops from the Palette
		"LinkDrawn" : showLinkLabel, // this DiagramEvent listener is
		"LinkRelinked" : showLinkLabel,
		scrollsPageOnFocus : false,
		"undoManager.isEnabled" : true,
		"grid.visible" : true,
		"commandHandler.deletesTree" : false
	});

	var cxElement = document.getElementById("contextMenu");
	var myContextMenu = $(go.HTMLInfo, {
		show : showContextMenu,
		mainElement : cxElement
	});

	// when the document is modified, add a "*" to the title and enable the
	// "Save" button
	myDiagram.addDiagramListener("Modified", function(e) {
		var button = document.getElementById("SaveButton");
		if (button)
			button.disabled = !myDiagram.isModified;
		var idx = document.title.indexOf("*");
		if (myDiagram.isModified) {
			if (idx < 0)
				document.title += "*";
		} else {
			if (idx >= 0)
				document.title = document.title.substr(0, idx);
		}
	});

	// helper definitions for node templates
	function nodeStyle() {
		return [
				// The Node.location comes from the "loc" property of the
				// node data,
				// converted by the Point.parse static method.
				// If the Node.location is changed, it updates the "loc"
				// property of the node data,
				// converting back using the Point.stringify static method.
				new go.Binding("location", "loc", go.Point.parse)
						.makeTwoWay(go.Point.stringify), {
					// the Node.location is at the center of each node
					locationSpot : go.Spot.Center,
					// isShadowed: true,
					// shadowColor: "#888",
					// handle mouse enter/leave events to show/hide the
					// ports
					mouseEnter : function(e, obj) {
						showPorts(obj.part, true);
					},
					mouseLeave : function(e, obj) {
						showPorts(obj.part, false);
					}
				} ];
	}

	// Define a function for creating a "port" that is normally transparent.
	// The "name" is used as the GraphObject.portId, the "spot" is used to
	// control how links connect
	// and where the port is positioned on the node, and the boolean
	// "output" and "input" arguments
	// control whether the user can draw links from or to the port.
	function makePort(name, spot, output, input) {
		// the port is basically just a small circle that has a white stroke
		// when it is made visible
		return $(go.Shape, "Circle", {
			fill : "transparent",
			stroke : null, // this is changed to "white" in the showPorts
			// function
			desiredSize : new go.Size(8, 8),
			alignment : spot,
			alignmentFocus : spot, // align the port on the main Shape
			portId : name, // declare this object to be a "port"
			fromSpot : spot,
			toSpot : spot, // declare where links may connect at this port
			fromLinkable : output,
			toLinkable : input, // declare whether the user may draw links
			// to/from here
			cursor : "pointer" // show a different cursor to indicate
		// potential link point
		});
	}

	function nodeStatusConverter(status) {
		if (status == -1)
			return "red";
		if (status >= 0)
			return "green";
		return "green";
	}

	// define the Node templates for regular nodes
	var lightText = 'whitesmoke';

	// the default category
	myDiagram.nodeTemplateMap.add("", $(go.Node, "Spot", nodeStyle(), $(
			go.Panel, "Auto", {
				contextMenu : myContextMenu
			}, $(go.Shape, "Rectangle", {
				fill : "#00A9C9",
				stroke : null
			}, new go.Binding("fill", "status", nodeStatusConverter),
					new go.Binding("figure", "figure")), $(go.TextBlock, {
				font : "bold 11pt Helvetica, Arial, sans-serif",
				stroke : lightText,
				margin : 8,
				maxSize : new go.Size(160, NaN),
				wrap : go.TextBlock.WrapFit,
				editable : true
			}, new go.Binding("text").makeTwoWay())), makePort("T",
			go.Spot.Top, false, true), makePort("L", go.Spot.Left, true, true),
			makePort("R", go.Spot.Right, true, true), makePort("B",
					go.Spot.Bottom, true, false)));

	// Start
	myDiagram.nodeTemplateMap.add("Start", $(go.Node, "Spot", nodeStyle(), $(
			go.Panel, "Auto", $(go.Shape, "Circle", {
				minSize : new go.Size(40, 40),
				fill : "#79C900",
				stroke : null
			}), $(go.TextBlock, "Start", {
				font : "bold 11pt Helvetica, Arial, sans-serif",
				stroke : lightText
			}, new go.Binding("text"))), makePort("L", go.Spot.Left, true,
			false), makePort("R", go.Spot.Right, true, false), makePort("B",
			go.Spot.Bottom, true, false)));

	// End
	myDiagram.nodeTemplateMap.add("End", $(go.Node, "Spot", nodeStyle(), $(
			go.Panel, "Auto", $(go.Shape, "Circle", {
				minSize : new go.Size(40, 40),
				fill : "#DC3C00",
				stroke : null
			}), $(go.TextBlock, "End", {
				font : "bold 11pt Helvetica, Arial, sans-serif",
				stroke : lightText
			}, new go.Binding("text"))),
			makePort("T", go.Spot.Top, false, true), makePort("L",
					go.Spot.Left, false, true), makePort("R", go.Spot.Right,
					false, true)));

	//comment
	myDiagram.nodeTemplateMap.add("Comment", $(go.Node, "Auto", nodeStyle(), $(
			go.Shape, "File", {
				fill : "#EFFAB4",
				stroke : null
			}), $(go.TextBlock, {
		margin : 5,
		maxSize : new go.Size(200, NaN),
		wrap : go.TextBlock.WrapFit,
		textAlign : "center",
		editable : true,
		font : "bold 12pt Helvetica, Arial, sans-serif",
		stroke : '#454545'
	}, new go.Binding("text").makeTwoWay())));

	// replace the default Link template in the linkTemplateMap
	myDiagram.linkTemplate = $(go.Link, // the whole link panel
	{
		routing : go.Link.AvoidsNodes,
		curve : go.Link.JumpOver,
		corner : 5,
		toShortLength : 4,
		relinkableFrom : true,
		relinkableTo : true,
		reshapable : true,
		resegmentable : true,
		// mouse-overs subtly highlight links:
		mouseEnter : function(e, link) {
			link.findObject("HIGHLIGHT").stroke = "rgba(30,144,255,0.2)";
		},
		mouseLeave : function(e, link) {
			link.findObject("HIGHLIGHT").stroke = "transparent";
		}
	}, new go.Binding("points").makeTwoWay(), $(go.Shape, // the highlight
	// shape,
	// normally
	// transparent
	{
		isPanelMain : true,
		strokeWidth : 8,
		stroke : "transparent",
		name : "HIGHLIGHT"
	}), $(go.Shape, // the link path shape
	{
		isPanelMain : true,
		stroke : "gray",
		strokeWidth : 2
	}), $(go.Shape, // the arrowhead
	{
		toArrow : "standard",
		stroke : null,
		fill : "gray"
	}), $(go.Panel, "Auto", // the link label, normally not visible
	{
		visible : false,
		name : "LABEL",
		segmentIndex : 2,
		segmentFraction : 0.5
	}, new go.Binding("visible", "visible").makeTwoWay(), $(go.Shape,
			"RoundedRectangle", // the label shape
			{
				fill : "#F8F8F8",
				stroke : null
			}), $(go.TextBlock, "Yes", // the label
	{
		textAlign : "center",
		font : "10pt helvetica, arial, sans-serif",
		stroke : "#333333",
		editable : true
	}, new go.Binding("text").makeTwoWay())));

	// Make link labels visible if coming out of a "conditional" node.
	// This listener is called by the "LinkDrawn" and "LinkRelinked"
	// DiagramEvents.
	function showLinkLabel(e) {
		var label = e.subject.findObject("LABEL");
		if (label !== null)
			label.visible = (e.subject.fromNode.data.figure === "Diamond");
	}

	// temporary links used by LinkingTool and RelinkingTool are also
	// orthogonal:
	myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
	myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;

	load(); // load an initial diagram from some JSON text

	// initialize the Palette that is on the left side of the page
	myPalette = $(go.Palette, "myPaletteDiv", // must name or refer to the
	{
		scrollsPageOnFocus : false,
		nodeTemplateMap : myDiagram.nodeTemplateMap,
		model : new go.GraphLinksModel([ // specify the contents of the
		// Palette
		{
			category : "Start",
			text : "开始"
		}, {
			text : "节点"
		}, {
			category : "Select",
			text : "分支",
			figure : "Diamond"
		}, {
			category : "End",
			text : "结束"
		}, {
			category : "Comment",
			text : "备注"
		} ])
	});

	myDiagram.contextMenu = myContextMenu;

	// We don't want the div acting as a context menu to have a (browser)
	// context menu!
	cxElement.addEventListener("contextmenu", function(e) {
		e.preventDefault();
		return false;
	}, false);

	function showContextMenu(obj, diagram, tool) {
		if (obj != null) {
			// console.log(obj.part.Zd.text);
			// console.log(obj.part.Zd.key);

			nodetext = obj.part.Zd.text;
			nodekey = obj.part.Zd.key;
		}

		// Show only the relevant buttons given the current state.
		var cmd = diagram.commandHandler;
		document.getElementById("cut").style.display = cmd.canCutSelection() ? "block"
				: "none";
		document.getElementById("copy").style.display = cmd.canCopySelection() ? "block"
				: "none";
		document.getElementById("paste").style.display = cmd
				.canPasteSelection() ? "block" : "none";
		document.getElementById("delete").style.display = cmd
				.canDeleteSelection() ? "block" : "none";

		// Now show the whole context menu element
		cxElement.style.display = "block";
		// we don't bother overriding positionContextMenu, we just do it here:
		var mousePt = diagram.lastInput.viewPoint;
		var bordleft = document.getElementById('myDiagramDiv')
				.getBoundingClientRect().left;
		var bordtop = document.getElementById('myDiagramDiv')
				.getBoundingClientRect().top;

		cxElement.style.left = bordleft + mousePt.x + "px";
		cxElement.style.top = bordtop + mousePt.y + "px";

	}
} // end init

// This is the general menu command handler, parameterized by the name of the
// command.
function cxcommand(event, val) {
	if (val === undefined)
		val = event.currentTarget.id;
	var diagram = myDiagram;
	switch (val) {
	case "cut":
		diagram.commandHandler.cutSelection();
		break;
	case "copy":
		diagram.commandHandler.copySelection();
		break;
	case "paste":
		diagram.commandHandler.pasteSelection(diagram.lastInput.documentPoint);
		break;
	case "delete":
		diagram.commandHandler.deleteSelection();
		break;
	case "eventbind":
		eventbind();
		break;
	}
	diagram.currentTool.stopTool();
}

function eventbind() {
	console.log('event bind');
	// console.log(nodetext);
	// console.log(nodekey);
	// console.log(tmpattr);

	// init modal
	var count = 0;
	for (var i = 0; i < tmpattr.length; i++) {
		if (tmpattr[i].nodekey == nodekey) {
			if (tmpattr[i].nodetype == 'server') {
				changeNodeTypeSelect(1);
				document.getElementById('nodetype').value = "server";
				document.getElementById('nodesource').value = tmpattr[i].nodesource;
				break;
			} else if (tmpattr[i].nodetype == 'database') {
				changeNodeTypeSelect(2);
				document.getElementById('nodetype').value = "database";
				document.getElementById('nodesource').value = tmpattr[i].nodesource;
				break;
			}
		}
		count++;
	}

	if (count == tmpattr.length) {
		changeNodeTypeSelect(0);
	}

	$('#myModal').removeClass('modalhide');
	$('#myModal').modal();
}

// node save in modal
function node_save() {
	var typeselect = document.getElementById('nodetype');
	var nodetype = typeselect.options[typeselect.selectedIndex].value;

	var sourceselect = document.getElementById('nodesource');
	var nodesource = sourceselect.options[sourceselect.selectedIndex].value;

	console.log(nodetype + ' ' + nodesource);
	var nodeattr = {
		"nodetext" : nodetext,
		"nodekey" : nodekey,
		"nodetype" : nodetype,
		"nodesource" : nodesource
	};
	nodeattrlist.push(nodeattr);

	var button = document.getElementById("SaveButton");
	button.disabled = false;
};

// Make all ports on a node visible when the mouse is over the node
function showPorts(node, show) {
	var diagram = node.diagram;
	if (!diagram || diagram.isReadOnly || !diagram.allowLink)
		return;
	node.ports.each(function(port) {
		port.stroke = (show ? "white" : null);
	});
}

function load() {
	myDiagram.model = go.Model
			.fromJson(document.getElementById("mySavedModel").value);
}

function changeNodeTypeSelect(index) {
	var ns = document.getElementById("nodesource");
	var svlist = JSON.parse($('#svlist').val());
	var dblist = JSON.parse($('#dblist').val());
	var mqlist = JSON.parse($('#mqlist').val());

	$('#nodesource').empty();
	if (index == 1) {
		for (var i = 0; i < svlist.length; i++) {
			var opt = new Option(svlist[i], svlist[i]);
			ns.add(opt);
		}
	} else if (index == 2) {
		for (var i = 0; i < dblist.length; i++) {
			var opt = new Option(dblist[i], dblist[i]);
			ns.add(opt);
		}
	} else if (index == 3) {
		for (var i = 0; i < mqlist.length; i++) {
			var opt = new Option(mqlist[i], mqlist[i]);
			ns.add(opt);
		}
	}
}